/* 
 *  <copyright file="SobrietyGame.cs" company="Wesley Jowitt">
 *  
 *  SobrietyEngine: Copyright (c) 2011 Wesley Jowitt
 *  
 *  This software is distributed under a software license.
 *   * As of the creation time of this file, the license in use is the Microsoft Permissive License (Ms-PL) 
 *    * The license can be viewed at:
 *     * License.Txt in the root folder of this project
 *      * http://sobrietyengine.codeplex.com/license
 *       * http://www.microsoft.com/opensource/licenses.mspx
 *       
 *  </copyright>
 *   */

/*
 * Sobriey Engine, sept. 23, 2008
 * Wes Jowitt
 * Everett Feldt
 * */


using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using SobrietyEngine.Actor;
using SobrietyEngine.Assets;
using SobrietyEngine.Commands;
using SobrietyEngine.Components;
using SobrietyEngine.Events;
using SobrietyEngine.Guids;
using SobrietyEngine.Input;
using SobrietyEngine.Logging;
using SobrietyEngine.PlayerData;
using SobrietyEngine.Processes;
using SobrietyEngine.Scene;
using SobrietyEngine.Screens;
using SobrietyEngine.Assets.Textures;

namespace SobrietyEngine.Games
{
    public class SobrietyGame : Microsoft.Xna.Framework.Game, SobrietyEngine.Games.ISobrietyGameServices
    {
        //Game services we can access at all times
        public EventRouterGameService EventRouterService { get; protected set; }
        public SceneGameService SceneGameService { get; protected set; }
        protected CommandManager commandManager;
        protected ProcessGameService processGameService;
        public InputGameService InputGameComponent { get; protected set; }
        public GuidGameService GuidGameService { get; protected set; }
        public ITextureManagerGameService TextureGameService { get; protected set; }
        public Physics.FarseerPhysicsService PhysicsGameService { get; protected set; }
        public ScreenManager ScreenGameService { get; protected set; }
        public ActorGameService ActorGameService { get; protected set; }
        public PlayerGameService PlayerGameService { get; protected set; }
        public Sound.SoundGameService SoundGameService { get; protected set; }
        public IAssetGameService AssetGameService { get; private set; }
        public SobrietyEngine.User.IUserGameService UserGameService { get; private set;  }

        private Logger LoggerGameService;

        //XNA objects
        public GraphicsDeviceManager GraphicDM { get; protected set;}
        protected SpriteBatch spriteBatch;
        public Viewport FullscreenViewport { get; protected set;}

        public SobrietyGame()
        {
            LoggerGameService = new Logger(this);
            this.Components.Add(LoggerGameService);
            
            
            GraphicDM = new GraphicsDeviceManager(this);            
#if XBOX360
            // On the 360, we are always fullscreen and we always render to the user's prefered resolution
            GraphicDM.PreferredBackBufferWidth = 1280;//this.Window.ClientBounds.Width;
            GraphicDM.PreferredBackBufferHeight = 720;//this.Window.ClientBounds.Height;
            // We also get multisampling essentially for free on the 360, so turn it on
            GraphicDM.PreferMultiSampling = true;
#endif

            Content.RootDirectory = "SEGameExampleContent";
            AssetGameService = new AssetGameService(this);
            this.Components.Add((IGameComponent)AssetGameService);
            AssetGameService.CreateContentManager("SobrietyEngine", "SobrietyEngineContent");
            //content = new ContentManager(Services);
            //content.RootDirectory = contentDirectory;

            //start worldUp our gameServices components
            //heres for our always active components
            EventRouterService = new EventRouterGameService(this);
            this.Components.Add(EventRouterService);

            UserGameService = new SobrietyEngine.User.UserGameService(this);
            this.Components.Add((IGameComponent)UserGameService);

            InputGameComponent = new InputGameService(this);
            this.Components.Add(InputGameComponent);

            processGameService = new ProcessGameService(this);
            this.Components.Add(processGameService);

            GuidGameService = new GuidGameService(this);
            this.Components.Add(GuidGameService);

            TextureGameService = new TextureManagerGameService(this);
            this.Components.Add((GameComponent)TextureGameService);

            ScreenGameService = new ScreenManager(this);
            this.Components.Add(ScreenGameService);

            //inactive until we need them to be activated
            PhysicsGameService = new Physics.FarseerPhysicsService(this);
            this.Components.Add(PhysicsGameService);
            PhysicsGameService.Enabled = false;
            PhysicsGameService.Visible = false;

            SceneGameService = new SceneGameService(this);
            this.Components.Add(SceneGameService);
            SceneGameService.Enabled = false;
            SceneGameService.Visible = false;

            ActorGameService = new ActorGameService(this);
            this.Components.Add(ActorGameService);

            PlayerGameService = new PlayerGameService(this);
            this.Components.Add(PlayerGameService);

            SoundGameService = new Sound.SoundGameService(this);
            this.Components.Add(SoundGameService);
          
        }

        private bool InitGraphicsMode(int iWidth, int iHeight, bool bFullScreen)
        {
            // If we aren't using a full screen mode, the height and width of the window can
            // be set to anything equal to or smaller than the actual screen size.
            if (bFullScreen == false)
            {
                if ((iWidth <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width)
                && (iHeight <= GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height))
                {
                    GraphicDM.PreferredBackBufferWidth = iWidth;                    
                    GraphicDM.PreferredBackBufferHeight = iHeight;
                    GraphicDM.IsFullScreen = bFullScreen;
                    GraphicDM.ApplyChanges();
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Allows the gameServices to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            base.Initialize();


            //we need to add all our componenets and register our objects with our factorie           
            InitGraphicsMode(1280, 720, false);

            FullscreenViewport = GraphicsDevice.Viewport;
            
            //SceneGameService.FullscreenViewport = FullscreenViewport;

            //cameraGameService.Fullscreen = GraphicsDevice.Viewport;

            ((IScreenManager)ScreenGameService).FullScreenViewport = FullscreenViewport;

            spriteBatch = new SpriteBatch(this.GraphicDM.GraphicsDevice);           

            //processes
            //ProcessFactory.Register(new TimerProcBldr());
            //ProcessFactory.Register(new CmdExecProcBldr());

            //commands
            //CommandFactory.Register(new SetPosCmdBldr());

            //Components
            //Register all components. This class registers them, thats its only job
            //its in aclass liek this so we can register components from the tools
            //without having to create an isntance of a gameServices.
            RegisterComponentsWithFactory.Register();
            RegisterBuildersWithFactory.Register();

            //event listeners
            //EventListenerFactory.Register(new EventSnooperLstnrBldr());
        }

        /// <summary>
        /// LoadContent will be called once per gameServices and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            //spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your gameServices content here
        }

        /// <summary>
        /// UnloadContent will be called once per gameServices and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the gameServices to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the gameServices should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
        }
    }
}